﻿using Action = Styx.TreeSharp.Action;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Styx.Pathing;
using System.Diagnostics;
using Styx.WoWInternals.Misc;
using System.Windows.Media;

namespace DestroLock
{
    public partial class Main : CombatRoutine
    {
        internal readonly Version Version = new Version(1, 0, 0);
        public override string Name { get { return "Pasterke's Destruction Warlock Combat Routine"; } }
        public override WoWClass Class { get { return WoWClass.Warlock; } }
        LocalPlayer Me { get { return StyxWoW.Me; } }

        private Composite _preCombatBuffs, _combatBuffs, _Heal, _Combat, _Pull, _pullBuffs;
        public override Composite PreCombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _preCombatBuffs; } }
        public override Composite CombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _combatBuffs; } }
        public override Composite HealBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Heal; } }
        public override Composite CombatBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Combat; } }
        public override Composite PullBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Pull; } }
        public override Composite PullBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _pullBuffs; } }
        public string usedBot { get { return BotManager.Current.Name; } }
        public bool NeedRes = false;
        public string LastPetCast = string.Empty;
        private static DateTime lastpull = DateTime.Now;

        private static Stopwatch petPresenceTimer = new Stopwatch();


        private static bool IsInGame
        {
            get { return StyxWoW.IsInGame; }
        }
        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form1 ConfigForm = new Form1();
            ConfigForm.ShowDialog();
        }

        public override void Pulse()
        {
            try
            {

                if (Me.Pet != null && Me.GotAlivePet && petPresenceTimer.IsRunning)
                {
                    LogMsg("[Pulse] Resetting pettimer", 8);
                    petPresenceTimer.Reset();
                }
                if (!Me.Combat && immolateTimer.IsRunning)
                {
                    LogMsg("[Pulse] Resetting immotimer", 8);
                    immolateTimer.Reset();
                }
                if ((Me.IsDead)
                    && !deadTimer.IsRunning)
                {
                    LogMsg("[Pulse] Restarting deadtimer", 8);
                    deadTimer.Restart();
                }
                if (!Me.IsDead
                    && deadTimer.IsRunning)
                {
                    LogMsg("[Pulse] Resetting deadtimer", 8);
                    deadTimer.Reset();
                }
                if ((Me.IsDead)
                    && deadTimer.ElapsedMilliseconds >= 5000
                    && LockSettings.myPrefs.Movement
                    && !Me.GroupInfo.IsInRaid
                    && !Me.GroupInfo.IsInLfgParty)
                {
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/run UseSoulstone()AcceptResurrect()RetrieveCorpse()"));

                    if (deadTimer.ElapsedMilliseconds >= 10 * 1000)
                    {
                        Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                    }
                }
                return;
            }
            catch { }
        }

        #region Initialize
        public override void Initialize()
        {
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", EventHandlers.HandleModifierStateChanged);
            Lua.Events.AttachEvent("UI_ERROR_MESSAGE", EventHandlers.CombatLogErrorHandler);

            _preCombatBuffs = createPreCombatBuffs();
            _combatBuffs = createCombatBuffs();
            //_Heal = createBuffs();
            _Combat = createCombat();
            _Pull = createPull();
            _pullBuffs = createPullBuffs();

        }
        #endregion

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", EventHandlers.HandleModifierStateChanged);
            Lua.Events.DetachEvent("UI_ERROR_MESSAGE", EventHandlers.CombatLogErrorHandler);
        }

        #region rest
        public override bool NeedRest
        {
            get
            {
                return Me.HealthPercent <= LockSettings.myPrefs.foodpercent
                    || Me.ManaPercent <= LockSettings.myPrefs.manapercent
                    || Me.Pet != null && Me.GotAlivePet && Me.Pet.HealthPercent <= LockSettings.myPrefs.funnelOOC
                    || (Me.Pet == null && !Me.Mounted && !Me.IsFlying);
            }
        }
        public override void Rest()
        {
            if (Me.Pet != null
                && Me.GotAlivePet
                && Me.Pet.HealthPercent <= LockSettings.myPrefs.funnelOOC
                && !Me.IsChanneling)
            {
                SpellManager.Cast("Health Funnel", Me.Pet);
                LogMsg("Healing my Pet", 0);
                LastSpell = "Health Funnel";
            }

            if (Me.Pet == null && !petPresenceTimer.IsRunning)
            {
                petPresenceTimer.Restart();
            }
            if (Me.Pet == null && petPresenceTimer.ElapsedMilliseconds >= 4500 && !Me.IsCasting && LastSpell != "summonpet")
            {
                SpellManager.Cast("Summon " + petName);
                LogMsg("Summon " + petName, 0);
                LastSpell = "summonpet";
                StyxWoW.SleepForLagDuration();
                petPresenceTimer.Reset();
            }
            if (Me.HealthPercent <= LockSettings.myPrefs.foodpercent
                && !Me.IsDead
                && !Me.IsGhost
                && !Me.IsSwimming)
            {
                Styx.CommonBot.Rest.Feed();
            }
            if (Me.ManaPercent <= LockSettings.myPrefs.manapercent
                && !Me.IsDead
                && !Me.IsGhost
                && !Me.IsSwimming)
            {
                Styx.CommonBot.Rest.Feed();
            }
            if (!buffExists("Soulstone", Me) && !Me.IsCasting)
            {
                if (LockSettings.myPrefs.createSoulstone == LockSettings.SoulstonePrefs.onMySelf
                    && !buffExists("Soulstone", Me)
                    && !Me.IsCasting)
                {
                    SpellManager.Cast("Soulstone", Me);
                    LogMsg("Creating Soulstone on myself", 2);
                    StyxWoW.SleepForLagDuration();
                }
                if (LockSettings.myPrefs.createSoulstone == LockSettings.SoulstonePrefs.onFocus
                    && Me.FocusedUnit != null
                    && !buffExists("Soulstone", Me.FocusedUnit)
                    && !Me.IsCasting)
                {
                    SpellManager.Cast("Soulstone", Me.FocusedUnit);
                    LogMsg("Creating Soulstone " + Me.FocusedUnit.Name, 2);
                    StyxWoW.SleepForLagDuration();
                }
            }
        }
        #endregion rest

        #region precombat buffs
        Composite createPreCombatBuffs()
        {
            return new PrioritySelector(
                IsPausedCombatRoutine(),
                CastBuff("Dark Intent", 0, ret => SpellManager.HasSpell("Dark Intent")
                    && !buffExists("Dark Intent", Me)),
                createHealthStone(),
                Cast("Unending Breath", 0, ret => SpellManager.HasSpell("Unending Breath")
                    && !buffExists("Unending Breath", Me)
                    && LastSpell != "Unending Breath"
                    && LockSettings.myPrefs.autoUnendingBreath
                    && Me.IsSwimming),
                useCrystalofInsanity(),
                useAlchemyFlask()
                );
        }
        #endregion precombat buffs

        #region combatbuffs
        Composite createCombatBuffs()
        {
            return new PrioritySelector(
                IsPausedCombatRoutine(),
                CastBuff("Dark Intent", 0, ret => SpellManager.HasSpell("Dark Intent")
                    && !buffExists("Dark Intent", Me)),
                useCrystalofInsanity(),
                useAlchemyFlask(),
                useMyFlask()
                );
        }

        #endregion combatbuffs
        #region Pull buffs
        Composite createPullBuffs()
        {
            return new PrioritySelector(

                        );
        }
        #endregion pull buffs

        #region Pull
        Composite createPull()
        {
            return new PrioritySelector(
                IsPausedCombatRoutine(),
                ensureTarget(),
                //movement
                createMoveInRange(35),
                createLignOfSight(),
                createStopMove(),
                createFacing(),
                //end movement
                Cast("Curse of the Elements", 8, ret => gotTarget
                    && SpellManager.HasSpell("Curse of the Elements")
                    && LockSettings.myPrefs.usePullSpell == LockSettings.pullSpell.Curse_of_the_Elements),
                Cast("Corruption", 8, ret => gotTarget
                    && SpellManager.HasSpell("Corruption")
                    && !SpellManager.HasSpell("Immolate")
                    && LockSettings.myPrefs.usePullSpell == LockSettings.pullSpell.Corruption),
                Cast("Curse of Enfeeblement", 8, ret => gotTarget
                    && SpellManager.HasSpell("Curse of Enfeeblement")
                    && LockSettings.myPrefs.usePullSpell == LockSettings.pullSpell.Curse_of_Enfeeblement),
                Cast("Immolate", 8, ret => gotTarget
                    && SpellManager.HasSpell("Immolate")
                    && LockSettings.myPrefs.usePullSpell == LockSettings.pullSpell.Immolate),
                Cast("Shadow Bolt", 8, ret => gotTarget
                    && SpellManager.HasSpell("Shadow Bolt")
                    && LockSettings.myPrefs.usePullSpell == LockSettings.pullSpell.Shadow_Bolt)
                        );
        }
        #endregion

        #region Combat
        Composite createCombat()
        {
            return new PrioritySelector(
                IsPausedCombatRoutine(),
                disMount(),
                clearMyTarget(),
                takePetsTarget(),
                ensureTarget(),
                checkBuggedMobs(),
                useHealthStone(),
                CallMyPet(),
                createSoulstone(),
                createHealthStone(),
                CastBuff("Unending Breath", 0, ret => SpellManager.HasSpell("Unending Breath")
                    && !buffExists("Unending Breath", Me)
                    && LastSpell != "Unending Breath"
                    && LockSettings.myPrefs.autoUnendingBreath
                    && Me.IsSwimming),
                Cast("Twilight Ward", 0, ret => gotTarget
                    && LockSettings.myPrefs.useTwilightWard && !buffExists("Twilight Ward", Me)
                    && LastSpell != "Twilight Ward"),
                CastBuff("Ember Tap", 0, ret => gotTarget
                    && Me.HealthPercent <= LockSettings.myPrefs.embertappercentpercent
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 35),
                CastBuff("Dark Bargain", 0, ret => gotTarget
                    && SpellManager.HasSpell("Dark Bargain")
                    && !spellOnCooldown("Dark Bargain")
                    && Me.HealthPercent <= LockSettings.myPrefs.darkBargainpercent),
                CastBuff("Soulshatter", 0, ret => gotTarget
                    && SpellManager.HasSpell("Soulshatter")
                    && (Me.IsInInstance || Me.GroupInfo.IsInRaid)
                    && Me.ThreatInfo.RawPercent >= 90),
                CastBuff("Unending Resolve", 0, ret => gotTarget
                    && SpellManager.HasSpell("Unending Resolve")
                    && Me.HealthPercent <= LockSettings.myPrefs.unendingResolve),
                Cast("Mortal Coil", 0, ret => gotTarget && SpellManager.HasSpell("Mortal Coil")
                    && !spellOnCooldown("Mortal Coil")
                    && Me.HealthPercent <= LockSettings.myPrefs.useMortalCoil),
                new Decorator(ret => Me.Level < 10, createLowbieRotation()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell("Rain of Fire")
                    && addCount >= LockSettings.myPrefs.startAoe
                    && !EventHandlers.PauseAoe, createAoe()),
                new Decorator(ret => Me.Level >= 10, createNormalRotation())
                        );
        }
        #endregion

        private Composite createLowbieRotation()
        {
            // Shadow Bolt lvl 1
            // Summon Deamon lvl 1
            // Corruption lvl 3
            // Drain Life lvl 7
            // Summon Voidwalker lvl 8
            // create healthstone lvl 9
            return new PrioritySelector(
                //movement
                createMoveInRange(35),
                createLignOfSight(),
                createStopMove(),
                createFacing(),
                //end movement
                Cast("Arcane Torrent", 0, ret => gotTarget
                    && Me.ManaPercent <= LockSettings.myPrefs.useArcaneTorrent
                    && !spellOnCooldown("Arcane Torrent")
                    && LastSpell != "Arcane Torrent"),
                Cast("Corruption", 1, ret => gotTarget
                    && SpellManager.HasSpell("Corruption")
                    && !debuffExists("Corruption", Me.CurrentTarget)
                    && LastSpell != "Corruption"
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Drain Life", 1, ret => gotTarget
                    && SpellManager.HasSpell("Drain Life")
                    && Me.HealthPercent <= LockSettings.myPrefs.useDrainLife
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Shadow Bolt", 1, ret => gotTarget
                    && SpellManager.HasSpell("Shadow Bolt")
                    && IsInRange(39, Me.CurrentTarget))
                );
        }
        private Composite createNormalRotation()
        {
            return new PrioritySelector(
                //movement
                createMoveInRange(35),
                createLignOfSight(),
                createStopMove(),
                createFacing(),
                //end movement
                MultiDotImmo(),
                Cast("Arcane Torrent", 0, ret => gotTarget
                    && Me.ManaPercent <= LockSettings.myPrefs.useArcaneTorrent
                    && !spellOnCooldown("Arcane Torrent")
                    && LastSpell != "Arcane Torrent"),
                Cast(DARK_SOUL, 3, ret => gotTarget
                        && SpellManager.HasSpell(DARK_SOUL)
                        && !spellOnCooldown(DARK_SOUL)
                        && LastSpell != DARK_SOUL.ToString()
                        && useDarksSoul),
                useIncreaseStatsPotion(),
                useTrinket1(),
                useTrinket2(),
                useEngiGloves(),
                Cast(castCurse(), 3, ret => gotTarget
                    && haveCurse()
                    && !debuffExists(castCurse(), Me.CurrentTarget)
                    && LastSpell != castCurse()),
                new Decorator(ret => gotTarget
                    && addCount > 1
                    && LastSpell != "Havoc", castHavoc()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell("Howl of Terror")
                    && !Me.GroupInfo.IsInRaid
                    && !Me.IsInInstance
                    && !spellOnCooldown("Howl of Terror")
                    && LastSpell != "Howl of Terror"
                    && addCount >= LockSettings.myPrefs.useHowlOfTerror,
                    HowlOfTerror()),
                Cast("Health Funnel", 3, ret => Me.GotAlivePet
                    && SpellManager.HasSpell("Health Funnel")
                    && Me.Pet.HealthPercent <= LockSettings.myPrefs.funnel
                    && Me.HealthPercent > LockSettings.myPrefs.useDrainLife),
                Cast("Drain Life", 3, ret => gotTarget
                    && SpellManager.HasSpell("Drain Life")
                    && Me.HealthPercent <= LockSettings.myPrefs.useDrainLife
                    && IsInRange(39, Me.CurrentTarget)),
                Cast(myInfernal, 3, ret => gotTarget
                    && !spellOnCooldown(myInfernal)
                    && LastSpell != myInfernal
                    && SummonMyInfernal()),
                Cast(doomGuard, 3, ret => gotTarget
                    && !spellOnCooldown(doomGuard)
                    && LastSpell != doomGuard
                    && SummonMyDoomGuard()),
                Cast("Immolate", 3, ret => gotTarget
                    && SpellManager.HasSpell("Immolate")
                    && !debuffExists("Immolate", Me.CurrentTarget)
                    && LastSpell != "Immolate"
                    && IsInRange(39, Me.CurrentTarget)),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(NEW_RAIN_OF_FIRE)
                    && LockSettings.myPrefs.useRainOfFire
                    && buffExists("Immolate", Me.CurrentTarget)
                    && !debuffExists(NEW_RAIN_OF_FIRE, Me.CurrentTarget)
                    && !buffExists(NEW_RAIN_OF_FIRE, Me)
                    && LastSpell != NEW_RAIN_OF_FIRE.ToString()
                    && IsInRange(35, Me.CurrentTarget), DropCast(NEW_RAIN_OF_FIRE, 3)),
                Cast("Chaos Bolt", 3, ret => gotTarget
                    && SpellManager.HasSpell("Chaos Bolt")
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 35
                    && Me.CurrentTarget.HealthPercent >= 20
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Shadowburn", 3, ret => gotTarget
                    && SpellManager.HasSpell("Shadowburn")
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 10
                    && Me.CurrentTarget.HealthPercent < 20
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Conflagrate", 3, ret => gotTarget
                    && SpellManager.HasSpell("Conflagrate")
                    && HaveSpellCharges > 0
                    && !spellOnCooldown("Conflagrate")
                    && LastSpell != "Conflagrate"
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Incinerate", 3, ret => gotTarget
                    && SpellManager.HasSpell("Incinerate")
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Fel Flame", 3, ret => gotTarget
                    && SpellManager.HasSpell("Fel Flame")
                    && IsInRange(39, Me.CurrentTarget))

                );
        }
        private Composite createAoe()
        {
            return new PrioritySelector(
                //movement
                createMoveInRange(35),
                createLignOfSight(),
                createStopMove(),
                createFacing(),
                //end movement
                MultiDotImmo(),
                Cast("Arcane Torrent", 0, ret => gotTarget
                    && Me.ManaPercent <= LockSettings.myPrefs.useArcaneTorrent
                    && !spellOnCooldown("Arcane Torrent")
                    && LastSpell != "Arcane Torrent"),
                new Decorator(ret => gotTarget && SpellManager.HasSpell("Howl of Terror")
                    && !Me.GroupInfo.IsInRaid
                    && !Me.IsInInstance
                    && !spellOnCooldown("Howl of Terror")
                    && LastSpell != "Howl of Terror"
                    && addCount >= LockSettings.myPrefs.useHowlOfTerror,
                    HowlOfTerror()),
                Cast(myInfernal, 6, ret => gotTarget
                    && !spellOnCooldown(myInfernal)
                    && LastSpell != myInfernal
                    && SummonMyInfernal()),
                Cast("Health Funnel", 3, ret => Me.GotAlivePet
                    && SpellManager.HasSpell("Health Funnel")
                    && Me.Pet.HealthPercent <= LockSettings.myPrefs.funnel
                    && Me.HealthPercent > LockSettings.myPrefs.useDrainLife),
                Cast("Drain Life", 3, ret => gotTarget
                    && SpellManager.HasSpell("Drain Life")
                    && Me.HealthPercent <= LockSettings.myPrefs.useDrainLife
                    && IsInRange(39, Me.CurrentTarget)),
                Cast("Fire and Brimstone", 6, ret => gotTarget
                    && SpellManager.HasSpell("Fire and Brimstone")
                    && LastSpell != "Fire and Brimstone"
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 35),

                castHavoc(),

                Cast("Shadowburn", 6, ret => gotTarget
                    && Me.CurrentTarget.HealthPercent < 20
                    && Me.GetCurrentPower(WoWPowerType.BurningEmbers) >= 35),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell(NEW_RAIN_OF_FIRE)
                    && LockSettings.myPrefs.useRainOfFire
                    && buffExists("Immolate", Me.CurrentTarget)
                    && !debuffExists(NEW_RAIN_OF_FIRE, Me.CurrentTarget)
                    && !buffExists(NEW_RAIN_OF_FIRE, Me)
                    && LastSpell != NEW_RAIN_OF_FIRE.ToString()
                    && IsInRange(35, Me.CurrentTarget), DropCast(NEW_RAIN_OF_FIRE, 3)),
                Cast("Conflagrate", 6, ret => gotTarget
                    && IsInRange(35, Me.CurrentTarget)
                    && SpellManager.HasSpell("Conflagrate")
                    && HaveSpellCharges > 0
                    && LastSpell != "Conflagrate"
                    && !spellOnCooldown("Conflagrate")),
                Cast("Incinerate", 6, ret => gotTarget
                    && IsInRange(35, Me.CurrentTarget)
                    && SpellManager.HasSpell("Incinerate")),
                new Decorator(ret => gotTarget
                    && !SpellManager.HasSpell(NEW_RAIN_OF_FIRE)
                    && LockSettings.myPrefs.useRainOfFire
                    && IsInRange(35, Me.CurrentTarget)
                    && !Me.IsChanneling, DropCast("Rain of Fire", 3))
                );
        }
        private Composite autoAttack()
        {
            return new PrioritySelector(
                    new Decorator(ret => !StyxWoW.Me.IsAutoAttacking,
                        new Action(ret =>
                        {
                            Lua.DoString("StartAttack()");
                            return RunStatus.Failure;
                        }))
                    );
        }
        private Composite IsPausedCombatRoutine()
        {
            return new Decorator(ret => EventHandlers.Paused,
                new Action(ret =>
            {
                return;
            }));
        }
    }
}

